package com.kaguya.chain;

/**
 * 行为型：责任链模式
 * 让多个对象可以处理同一个请求，使多个对象连成一条链
 * 应用：servlet的filterChain，security的各个filter，js的事件冒泡等
 * 使用：拦截的类都实现统一接口，在自身聚合自身，满足条件则进行处理
 */
public class Test {
    public static void main(String[] args) {
        // 获取责任链
        AbstractLogger chainOfLoggers = getChainOfLoggers();

        // 模拟不同程度的请求，责任链动态根据需求调用指定的责任链
        chainOfLoggers.logMessage(AbstractLogger.DEBUG,"this is a debug message");
        System.out.println("----------------");
        chainOfLoggers.logMessage(AbstractLogger.ERROR,"this is a error message");
        System.out.println("----------------");
        chainOfLoggers.logMessage(AbstractLogger.INFO,"this is a info message");
    }

    /**
     * 返回一条logger的责任链
     */
    public static AbstractLogger getChainOfLoggers() {
        AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
        AbstractLogger debugLogger = new DebugLogger(AbstractLogger.DEBUG);
        AbstractLogger infoLogger = new InfoLogger(AbstractLogger.INFO);
        // 设置每个logger的下一条责任链
        errorLogger.setNextLogger(debugLogger);
        debugLogger.setNextLogger(infoLogger);

        return errorLogger;
    }
}

abstract class AbstractLogger {
    public static final int INFO = 1;
    public static final int DEBUG = 2;
    public static final int ERROR = 3;

    protected int level;

    /**
     * 责任链中的下一个元素
     */
    protected AbstractLogger nextLogger;

    public void setNextLogger(AbstractLogger nextLogger) {
        this.nextLogger = nextLogger;
    }

    /**
     * 调用方法前，进行的责任分配逻辑判断
     *
     * @param level
     * @param message
     */
    public void logMessage(int level, String message) {
        if (this.level <= level) {
            writeLog();
        }
        if (nextLogger != null) {
            nextLogger.logMessage(level, message);
        }
    }

    /**
     * 具体的实际方法
     */
    abstract protected void writeLog();
}

class InfoLogger extends AbstractLogger {

    public InfoLogger(int level) {
        super.level = level;
    }

    @Override
    protected void writeLog() {
        System.out.println("info.logger");
    }
}

class DebugLogger extends AbstractLogger {

    public DebugLogger(int level) {
        super.level = level;
    }

    @Override
    protected void writeLog() {
        System.out.println("debug.logger");
    }
}

class ErrorLogger extends AbstractLogger {

    public ErrorLogger(int level) {
        super.level = level;
    }

    @Override
    protected void writeLog() {
        System.out.println("error.logger");
    }
}
